// 作业评分系统工具函数
import type { GradingResult } from '@/types'
import html2canvas from 'html2canvas'

// 从 types 文件导入接口，不再在此定义

/**
 * 主要评分函数
 * @param {string} code - HTML代码
 * @param {number} assignmentId - 作业ID
 * @returns {GradingResult} 评分结果
 */
/**
 * 评分作业（异步版本，支持图像对比）
 * @param {string} code - 学生代码
 * @param {number} assignmentId - 作业ID
 * @param {string} referenceImagePath - 标准答案图片路径（可选）
 * @returns {Promise<GradingResult>} 评分结果
 */
export const gradeAssignment = async (
  code: string,
  assignmentId: number,
  referenceImagePath?: string
): Promise<GradingResult> => {
  const result = {
    score: 0,
    maxScore: 100,
    details: {
      visual: { score: 0, maxScore: 100, feedback: '' }
    },
    feedback: '',
    grade: 'F'
  }

  // 图片对比功能 (100分)
  let visualScore: { score: number; feedback: string }
  if (referenceImagePath) {
    visualScore = await checkVisualSimilarityWithImage(code, assignmentId, referenceImagePath)
  } else {
    // 如果没有参考图片，回退到基础评分
    visualScore = { score: 35, feedback: '未提供参考图片，给予基础分数' }
  }

  result.details.visual = { score: visualScore.score, maxScore: 100, feedback: visualScore.feedback }
  result.score = visualScore.score

  // 生成等级
  if (result.score >= 63)
    result.grade = 'A' // 90%
  else if (result.score >= 56)
    result.grade = 'B' // 80%
  else if (result.score >= 49)
    result.grade = 'C' // 70%
  else if (result.score >= 42)
    result.grade = 'D' // 60%
  else result.grade = 'F'

  // 生成总体反馈
  result.feedback = visualScore.feedback

  return result
}

/**
 * 评分作业（同步版本，向后兼容）
 * @param {string} code - 学生代码
 * @param {number} assignmentId - 作业ID
 * @returns {GradingResult} 评分结果
 */
export const gradeAssignmentSync = (code: string, assignmentId: number): GradingResult => {
  const result = {
    score: 35,
    maxScore: 100,
    details: {
      visual: { score: 35, maxScore: 100, feedback: '同步版本，给予基础分数' }
    },
    feedback: '同步版本，给予基础分数',
    grade: 'D'
  }

  return result
}

/**
 * 检查内容完整性
 * @param {string} code - HTML代码
 * @param {number} assignmentId - 作业ID
 * @returns {object} 内容评分结果
 */
/**
 * 智能内容检查函数 - 改进版（异步版本，支持图像对比）
 * 使用多维度评估方法，包括DOM结构分析、语法检查和功能性验证
 */
export const checkContent = async (
  code: string,
  assignmentId: number,
  referenceImagePath?: string
): Promise<{ score: number; maxScore: number; feedback: string }> => {
  const maxScore: number = 100 // 原内容30分 + 质量25分 + 创新性15分

  if (!code || !code.trim()) {
    return { score: 0, maxScore, feedback: '代码为空' }
  }

  try {
    // 如果提供了参考图片路径，进行图像对比
    let visualScore: { score: number; feedback: string }
    if (referenceImagePath) {
      visualScore = await checkVisualSimilarityWithImage(code, assignmentId, referenceImagePath)
    } else {
      // 如果没有参考图片，给予基础分数
      visualScore = { score: 35, feedback: '未提供参考图片，给予基础分数' }
    }

    return {
      score: Math.min(visualScore.score, maxScore),
      maxScore,
      feedback: visualScore.feedback || '代码结构良好'
    }
  } catch (error) {
    console.error('代码检查出错:', error)
    return { score: 0, maxScore, feedback: '代码检查出错' }
  }
}

/**
 * 检查视觉相似度对比（使用浏览器兼容的图像对比）
 * @param {string} code - HTML代码
 * @param {number} assignmentId - 作业ID
 * @param {string} referenceImagePath - 标准答案图片路径
 * @returns {Promise<object>} 视觉相似度评分结果
 */
async function checkVisualSimilarityWithImage(
  code: string,
  assignmentId: number,
  referenceImagePath: string
): Promise<{ score: number; feedback: string }> {
  try {
    // 使用浏览器兼容的方法进行图像对比
    const similarity = await compareWithReferenceImage(code, referenceImagePath)
    const score = Math.round(similarity * 100) 

    let feedback = ''
    if (similarity >= 0.9) {
      feedback = '视觉效果与标准答案高度相似'
    } else if (similarity >= 0.7) {
      feedback = '视觉效果与标准答案较为相似'
    } else if (similarity >= 0.5) {
      feedback = '视觉效果与标准答案有一定差异'
    } else {
      feedback = '视觉效果与标准答案差异较大'
    }

    return { score, feedback }
  } catch (error) {
    console.error('图像对比失败:', error)
    // 如果图像对比失败，回退到基础分数
    return { score: 35, feedback: '图像对比失败，给予基础分数' }
  }
}

/**
 * 使用浏览器Canvas API进行图像对比
 * @param {string} code - HTML代码
 * @param {string} referenceImagePath - 参考图片路径
 * @returns {Promise<number>} 相似度分数 (0-1)
 */
async function compareWithReferenceImage(
  code: string,
  referenceImagePath: string
): Promise<number> {
  try {
    // 创建一个隐藏的iframe来渲染代码
    const iframe = document.createElement('iframe')
    iframe.style.position = 'absolute'
    iframe.style.left = '-9999px'
    iframe.style.width = '1200px'
    iframe.style.height = '800px'
    iframe.style.border = 'none'
    document.body.appendChild(iframe)

    // 设置iframe内容
    const iframeDoc = iframe.contentDocument || iframe.contentWindow?.document
    if (!iframeDoc) {
      throw new Error('无法访问iframe文档')
    }

    iframeDoc.open()
    iframeDoc.write(code)
    iframeDoc.close()

    // 等待内容加载
    await new Promise(resolve => setTimeout(resolve, 1000))

    // 使用html2canvas截图
    const canvas = await html2canvas(iframeDoc.body, {
      width: 1200,
      height: 800,
      useCORS: true
    })

    // 加载参考图片
    const referenceImage = await loadImage(referenceImagePath)

    // 比较图片
    const similarity = await compareCanvasImages(canvas, referenceImage)

    // 清理
    document.body.removeChild(iframe)

    return similarity
  } catch (error) {
    console.error('浏览器图像对比失败:', error)
    // 回退到基于代码特征的相似度计算
    return calculateCodeSimilarity(code)
  }
}

/**
 * 加载图片到Canvas
 * @param {string} imagePath - 图片路径
 * @returns {Promise<HTMLCanvasElement>} Canvas元素
 */
function loadImage(imagePath: string): Promise<HTMLCanvasElement> {
  return new Promise((resolve, reject) => {
    const img = new Image()
    img.crossOrigin = 'anonymous'
    img.onload = () => {
      const canvas = document.createElement('canvas')
      canvas.width = 1200
      canvas.height = 800
      const ctx = canvas.getContext('2d')

      if (ctx) {
        ctx.drawImage(img, 0, 0, 1200, 800)
        resolve(canvas)
      } else {
        reject(new Error('无法获取Canvas上下文'))
      }
    }

    img.onerror = () => reject(new Error('图片加载失败'))
    img.src = imagePath
  })
}

/**
 * 比较两个Canvas图像
 * @param {HTMLCanvasElement} canvas1 - 第一个Canvas
 * @param {HTMLCanvasElement} canvas2 - 第二个Canvas
 * @returns {Promise<number>} 相似度分数 (0-1)
 */
async function compareCanvasImages(
  canvas1: HTMLCanvasElement,
  canvas2: HTMLCanvasElement
): Promise<number> {
  const ctx1 = canvas1.getContext('2d')
  const ctx2 = canvas2.getContext('2d')

  if (!ctx1 || !ctx2) {
    throw new Error('无法获取Canvas上下文')
  }

  const imageData1 = ctx1.getImageData(0, 0, canvas1.width, canvas1.height)
  const imageData2 = ctx2.getImageData(0, 0, canvas2.width, canvas2.height)

  const data1 = imageData1.data
  const data2 = imageData2.data

  let diffPixels = 0
  const totalPixels = data1.length / 4

  // 简化的像素对比（每4个值为一个像素：RGBA）
  for (let i = 0; i < data1.length; i += 4) {
    const r1 = data1[i],
      g1 = data1[i + 1],
      b1 = data1[i + 2]
    const r2 = data2[i],
      g2 = data2[i + 1],
      b2 = data2[i + 2]

    // 计算颜色差异
    const diff = Math.sqrt(Math.pow(r1 - r2, 2) + Math.pow(g1 - g2, 2) + Math.pow(b1 - b2, 2))

    // 如果差异超过阈值，认为是不同像素
    if (diff > 30) {
      diffPixels++
    }
  }

  return 1 - diffPixels / totalPixels
}

/**
 * DOM结构对比（备用方案）
 * @param {Document} doc - 文档对象
 * @param {string} referenceImagePath - 参考图片路径
 * @returns {Promise<number>} 相似度分数 (0-1)
 */
async function compareDOMStructure(doc: Document, referenceImagePath: string): Promise<number> {
  // 简化的DOM结构分析
  const elements = doc.querySelectorAll('*')
  const elementTypes = Array.from(elements).map(el => el.tagName.toLowerCase())
  const elementCount = elementTypes.length

  // 基于元素数量和类型的简单相似度计算
  // 这是一个简化的实现，实际应用中可以更复杂
  const expectedElementCount = 20 // 假设的期望元素数量
  const countSimilarity = Math.max(
    0,
    1 - Math.abs(elementCount - expectedElementCount) / expectedElementCount
  )

  return Math.min(countSimilarity, 0.8) // 最高0.8分，因为这是简化方案
}

/**
 * 基于代码特征的相似度计算（最后备用方案）
 * @param {string} code - HTML代码
 * @returns {number} 相似度分数 (0-1)
 */
function calculateCodeSimilarity(code: string): number {
  // 基于代码特征的简单相似度计算
  let score = 0

  // 检查基本HTML结构
  if (code.includes('<html>') && code.includes('<body>')) score += 0.2
  if (code.includes('<style>') || code.includes('style=')) score += 0.2
  if (code.includes('<div>') || code.includes('<section>')) score += 0.1
  if (code.includes('<input>') || code.includes('<button>')) score += 0.2
  if (code.includes('<ul>') || code.includes('<li>')) score += 0.1

  // 检查CSS特征
  if (/background|color|padding|margin/.test(code)) score += 0.1
  if (/flex|grid|position/.test(code)) score += 0.1

  return Math.min(score, 1)
}

/**
 * 下载代码文件
 * @param {string} content - 代码内容
 * @param {string} filename - 文件名（默认为 'code.html'）
 * @param {Function} showStatus - 状态显示函数
 */
export const downloadCode = (
  content: string,
  filename: string = 'code.html',
  showStatus?: (message: string, type: 'success' | 'warning' | 'error' | 'info') => void
) => {
  if (!content.trim()) {
    showStatus?.('代码内容为空，无法下载', 'warning')
    return
  }
  
  // 创建Blob对象
  const blob = new Blob([content], { type: 'text/html;charset=utf-8' })
  
  // 创建下载链接
  const url = URL.createObjectURL(blob)
  const link = document.createElement('a')
  link.href = url
  link.download = filename
  
  // 触发下载
  document.body.appendChild(link)
  link.click()
  
  // 清理
  document.body.removeChild(link)
  URL.revokeObjectURL(url)
  
  showStatus?.('代码文件已下载', 'success')
}
